package nl.nhl.idp.Views;

import java.io.IOException;

import nl.nhl.idp.R;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

public class SteeringView extends View
{
	//TODO: clean commented code!
//	private final int DIAL_OUTER_WIDTH = 25;
	
	//threshold for normal steering
	private int STEERING_NORMAL = 20;
	
	//threshold for hard steering
	private int STEERING_HARD = 80;
	
	//this value is added to the displayed value to correct sensor inaccuracy
	public static float VALUE_OFFSET = 0;
	
	private float value;
//	private float value_External;
	
	private Bitmap needleBMP;
	private Matrix m;
	
//	private RectF dialBoxOuter;
	private RectF dialBox;
	
	private Paint dialPaintStroke;
//	private Paint dialPaintOuterFill;
	private Paint dialPaintFill;
	
//	private Paint needlePaintOuter;
	private Paint needlePaintBMP;
	private Paint textPaint;
	private int centerX;
	private int centerY;
	//private int radius;
	
	public SteeringView(Context context)
	{
		this(context, null);
	}
	
	public SteeringView(Context context, AttributeSet attrs) 
	{
		this(context, attrs, 0);
	}
	
	public SteeringView(Context context, AttributeSet attrs, int defStyle) 
	{
		super(context, attrs, defStyle);

		// check if we are using attributes
		if(attrs != null)
		{
			// get typedArray of attributes
			TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SteeringViewAttr);
			
			// get the attributes
			STEERING_NORMAL = a.getInt(R.styleable.SteeringViewAttr_steer_normal, 20);
			STEERING_HARD = a.getInt(R.styleable.SteeringViewAttr_steer_hard, 75);
		}

		InitSteeringView(context.getAssets());
	}
	
	private void InitSteeringView(AssetManager assets)
	{
		
		
		if(!this.isInEditMode())
		{
			try
			{
				needleBMP = BitmapFactory.decodeStream(assets.open("images/dial_needle.png"));
			}
			catch(IOException ioe)
			{
				//let's just say we'll make sure it's there:)
			}
		}
		
		dialPaintStroke = new Paint(Paint.ANTI_ALIAS_FLAG);
		dialPaintStroke.setColor(Color.BLACK);
		dialPaintStroke.setStrokeWidth(3);
		dialPaintStroke.setStyle(Paint.Style.STROKE);

//		needlePaintOuter = new Paint(Paint.ANTI_ALIAS_FLAG);
//		needlePaintOuter.setColor(Color.WHITE);
//		needlePaintOuter.setStrokeWidth(3);
//		needlePaintOuter.setStyle(Paint.Style.FILL_AND_STROKE);
		
//		dialPaintOuterFill = new Paint(Paint.ANTI_ALIAS_FLAG);
//		dialPaintOuterFill.setColor(Color.GREEN);
//		dialPaintOuterFill.setStyle(Paint.Style.FILL);
		
		dialPaintFill = new Paint(Paint.ANTI_ALIAS_FLAG);
		dialPaintFill.setColor(Color.GREEN);
		dialPaintFill.setStyle(Paint.Style.FILL);
		
		needlePaintBMP = new Paint();
		needlePaintBMP.setFilterBitmap(true);
				
		textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		textPaint.setColor(Color.BLACK);
		textPaint.setStrokeWidth(1);
		textPaint.setStyle(Paint.Style.STROKE);
		
		if(this.isInEditMode())
		{
			//radius = 100;
			centerX = 200;
			centerY = 100;
			
			dialBox = new RectF(5, 5, 100*2-5, 200-5);
			//dialBox = new RectF(DIAL_OUTER_WIDTH, DIAL_OUTER_WIDTH, 100*2-DIAL_OUTER_WIDTH, 200-DIAL_OUTER_WIDTH);
		}
	}
	
	public void setValue(float value)
	{
		//get value from sensor pitch
		value = (-value)+VALUE_OFFSET;
		
		//clip values between -90 and 90
		if(value > 90)
			value = 90;
		if(value < -90)
			value = -90;
		
		int red = (int)((value < 0? -value:value)/90.0f*510);
		int grn = 510-(int)((value < 0? -value:value)/90.0f*510);
		
		if(grn > 255)
			grn = 255;
		if(red > 255)
			red = 255;
		
		dialPaintFill.setColor(Color.rgb(red, grn, 0));
		
		//image matrix
		m = new Matrix();
		m.postRotate(value, needleBMP.getWidth()/2, needleBMP.getHeight()-(needleBMP.getWidth()/2));
		m.postTranslate(centerX-needleBMP.getWidth()/2, centerY-(needleBMP.getHeight()-(needleBMP.getWidth()/2))+5);
		
		
		this.value = value;
		//redraw view
		invalidate();
	}
	
//	public void setValueExternal(float value)
//	{
//		//get value from sensor pitch
//		value = (-value)+VALUE_OFFSET;
//		
//		//clip values between -90 and 90
//		if(value > 90)
//			value = 90;
//		if(value < -90)
//			value = -90;
//		
//		int red = (int)((value < 0? -value:value)/90.0f*510);
//		int grn = 510-(int)((value < 0? -value:value)/90.0f*510);
//		
//		if(grn > 255)
//			grn = 255;
//		if(red > 255)
//			red = 255;
//		
//		dialPaintOuterFill.setColor(Color.rgb(red, grn, 0));
//		
//		this.value_External = value;
//		//redraw view
//		invalidate();
//	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		
		int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
		int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
		
		setMeasuredDimension(measuredWidth, measuredHeight);
		
		//set dial radius
		//radius = this.getHeight()-5;
		
		//set dial center
		centerX = this.getWidth()/2;
		centerY = this.getHeight();
		
		//re-create dial box
		dialBox = new RectF(5, 5, this.getHeight()*2-5, this.getWidth()-5);
		//dialBox = new RectF(DIAL_OUTER_WIDTH, DIAL_OUTER_WIDTH, this.getHeight()*2-DIAL_OUTER_WIDTH, this.getWidth()-DIAL_OUTER_WIDTH);
		
		
		if(needleBMP != null&&!this.isInEditMode())
		{
			//get bitmap height/width ratio
			float factor = (float)needleBMP.getHeight()/(float)needleBMP.getWidth();
			
			//scale the bitmap
			if(this.getHeight() > 0 && this.getWidth() > 0)
			{
				needleBMP = Bitmap.createScaledBitmap(needleBMP, (int)(this.getHeight()/factor), this.getHeight(), true);
			}
			
			//re-create image matrix
			m = new Matrix();
			m.postRotate(value, needleBMP.getWidth()/2, needleBMP.getHeight()-needleBMP.getWidth()/2);
			m.postTranslate(centerX-needleBMP.getWidth()/2, centerY-(needleBMP.getHeight()-(needleBMP.getWidth()/2))+5);
		}
	}
	
	@Override
	protected void onDraw(Canvas canvas)
	{
//		//draw outer dial fill
//		canvas.drawArc(dialBoxOuter, 180, 180, true, dialPaintOuterFill);
//		
//		//draw outer dial needle
//		canvas.drawArc(dialBoxOuter, 270+value_External-(5*0.5f), 5, true, needlePaintOuter);
		
		//draw inner dial fill
		canvas.drawArc(dialBox, 180, 180, true, dialPaintFill);
		
		//draw dial regions
		canvas.drawArc(dialBox, 180, 180, true, dialPaintStroke);
		canvas.drawArc(dialBox, 270-STEERING_HARD, (STEERING_HARD*2), true, dialPaintStroke);
		canvas.drawArc(dialBox, 270-STEERING_NORMAL, (STEERING_NORMAL*2), true, dialPaintStroke);
		
		if(!this.isInEditMode())
		{
			canvas.drawBitmap(needleBMP, m, needlePaintBMP);
		}
	}
}
